//
// Created by ta&to on 2022/9/28.
//
#include "http_connect.h"
#ifdef SOCKET_SERVER_SELECT
#define SELECTRDNEW	0x2000
void _init_select(log_t *logt, struct http_socket_event_loop_s *hset) {
    hset->current_link = 0;
    hset->select_ev_fds = (struct select_event*)http_calloc(hset->max_link * sizeof(struct select_event));
}
// 初始化fds结构体数组
void _create_select(log_t *logt, struct http_socket_event_loop_s *hset) {
    for (int i = 0; i < hset->max_link; hset->select_ev_fds[i].fd = -1, hset->select_ev_fds[i].events = 0, ++i);
}
void _add_event(log_t *logt, struct http_socket_event_loop_s *hset, int fd, uint32_t event) {
    hset->current_fd = fd;
    if(hset->current_link < hset->max_link)
    {
        for(int i = 0; i < hset->max_link; ++i) {
            if (hset->select_ev_fds[i].fd == -1) {
                hset->select_ev_fds[i].fd = fd;
                hset->select_ev_fds[i].events = event;
                break;
            }
        }
        atomicIncr(hset->current_link, 1);
        hset->maxfd = fd > hset->maxfd ? fd : hset->maxfd;
    }else{
        error(logt, "max connections arrive, maxconn is %d current accept fd is %d exit\n", hset->current_link, fd);
        putData(logt, fd,"bye",4);
        CloseAll(logt, 0, fd);
    }
}
static int _del_event(log_t *logt, struct http_socket_event_loop_s *hset, int i) {
    int fd = hset->select_ev_fds[i].fd;
    hset->select_ev_fds[i].fd = -1;
    hset->select_ev_fds[i].events = 0;
    FD_CLR(fd,&hset->rfds);
    atomicDecr(hset->current_link, 1);
    return fd;
}

void init_select(log_t *logt, struct http_socket_event_loop_s *hset) {
    _init_select(logt, hset);
}

void create_select(log_t *logt, struct http_socket_event_loop_s *hset) {
    _create_select(logt, hset);
}

void add_event(log_t *logt, struct http_socket_event_loop_s *hset, int fd, uint32_t event) {
    _add_event(logt, hset, fd, event);
}

int del_event(log_t *logt, struct http_socket_event_loop_s *hset, int i) {
    _del_event(logt, hset, i);
}

// 处理客户端发送来的数据
int _fd_handler(log_t *logt, struct http_socket_event_loop_s *hset, int listenfd) {   // 循环查询select容器
    int i = 0;
    for (; i < hset->max_link; i++) {
        if(hset->select_ev_fds[i].fd == -1)
            continue;
        int fd = hset->select_ev_fds[i].fd;
        if(FD_ISSET(fd,&hset->rfds)) {
            if(fd == listenfd){
                http_socket_event_handle_t * handler = copy_func_handler(hset);
                int client_fd = conn_handler(logt, hset, handler);

                mutex_lock(&hset->hgdefc->event_fun_lock);
                char *fdc = (char *) http_calloc(sizeof(char) * http_numlen(client_fd) + 1);
                memset(fdc, 0, sizeof(fdc));
                http_sprintf(fdc, "%d", client_fd);
                do{             // 只要有修改的可能就要删除再添加，防止野指针问题
                    RBtreenodedel(&hset->hgdefc->func_handler, fdc);
                } while (!RBtreenodeadd(&hset->hgdefc->func_handler, fdc, handler));
                http_free(fdc);
                mutex_unlock(&hset->hgdefc->event_fun_lock);

//                socketNonBlock(logt, client_fd);
                add_event(logt, hset, client_fd, SELECTRDNEW);
            }else{
                hset->current_fd = hset->select_ev_fds[i].fd;
                debug(logt, "检查到[%d]有数据到达", hset->select_ev_fds[i].fd);
                hset->current_fd = hset->select_ev_fds[i].fd;

                mutex_lock(&hset->hgdefc->event_fun_lock);
                char *fdc = (char *) http_calloc(sizeof(char) * http_numlen(hset->select_ev_fds[i].fd) + 1);
                memset(fdc, 0, sizeof(fdc));
                http_sprintf(fdc, "%d", hset->select_ev_fds[i].fd);
                noder node = RBtreenodesel(&hset->hgdefc->func_handler, fdc);
                if(ISNULL(node)){
                    mutex_unlock(&hset->hgdefc->event_fun_lock);
                    continue;
                }
                http_socket_event_handle_t * handler = (http_socket_event_handle_t *)node->spot->value;
                http_free(fdc);
                mutex_unlock(&hset->hgdefc->event_fun_lock);

                if(ISNOTNULL(handler->func_read))
                    handler->func_read(hset,  del_event(logt, hset, i), i);
            }
        }
    }
}
static void _reloadSelect(struct http_socket_event_loop_s *hset){
    FD_ZERO(&hset->rfds);
    for(int i = 0; i < hset->max_link; i++)
        if(hset->select_ev_fds[i].fd != -1)
            FD_SET(hset->select_ev_fds[i].fd,&hset->rfds);   // 将容器中的数据加入到select引擎
}
// 初始化fds结构体数组
void _select_loop(log_t *logt, struct http_socket_event_loop_s *hset)
{
    while(1){
        _reloadSelect(hset);                        // 重构数据
        if((select(hset->maxfd + 1, &hset->rfds, NULL, NULL, hset->tvp)) <= 0)
        {
            error(logt,"select err:[%s]", strerror(errno));
            continue;
        }
        _fd_handler(logt, hset, hset->socket_fd);
    }
}
int Select_do(log_t *logt, struct http_socket_event_loop_s *hset) {
    init_select(logt, hset);
    create_select(logt, hset);
    add_event(logt, hset, hset->socket_fd, SELECTRDNEW);
    _select_loop(logt, hset);
}

int Select_IO(log_t *logt, struct http_socket_event_loop_s *hset) {
    Select_do(logt, hset);
}
#endif